//
//  Snowflake.swift
//  SCA
//
//  Created by tjun on 2025/9/2.
//

import Foundation

class Snowflake {
    
     static let shared = Snowflake(datacenterId: 1, machineId: 1)

     private var datacenterId: Int64
     private var machineId: Int64
     private var sequence: UInt64
     private var lastTimestamp: UInt64
     private let epoch: UInt64 = 1609459200000 // 2021-01-01 UTC

     private init(datacenterId: Int64, machineId: Int64) {
        self.datacenterId = datacenterId & 0x1F // 5 位
        self.machineId = machineId & 0x1F       // 5 位
        self.sequence = 0
        self.lastTimestamp = 0
    }
    
    func nextId() -> UInt64 {
        synchronized(self) {
            var timestamp = UInt64(Date().timeIntervalSince1970 * 1000)
            
            if timestamp == lastTimestamp {
                sequence = (sequence + 1) & 0xFFF // 12 位
                if sequence == 0 {
                    while timestamp <= lastTimestamp {
                        timestamp = UInt64(Date().timeIntervalSince1970 * 1000)
                    }
                }
            } else {
                sequence = 0
            }
            
            lastTimestamp = timestamp
            
            return ((timestamp - epoch) & 0x1FFFFFFFFFF) << 22 |
            (UInt64(datacenterId) << 17) |
            (UInt64(machineId) << 12) |
            sequence
        }
    }
    
    func nextIdData() -> Data {
        var id = nextId().littleEndian
        return Data(bytes: &id, count: MemoryLayout<UInt64>.size)
    }
    
    private func synchronized(_ lock: Any, closure: () -> UInt64) -> UInt64 {
        objc_sync_enter(lock)
        defer { objc_sync_exit(lock) }
        return closure()
    }
    
}

